package com.example;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class UnsafeTest {

    private volatile int anInt = 0;

    public static Unsafe getUnsafe(){
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            Object unsafe = field.get(null);
            field.setAccessible(false);
            return (Unsafe) unsafe;
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public void increment() {
        Unsafe unsafe = getUnsafe();
        long offset = 0;
        try {
            offset = unsafe.objectFieldOffset(UnsafeTest.class.getDeclaredField("anInt"));
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        int current, next;
        do{
            current = this.anInt;
            next = current + 1;
        }while (!unsafe.compareAndSwapInt(this, offset, current, next));
    }

    public static void main(String[] args) throws InterruptedException {

        UnsafeTest unsafeTest = new UnsafeTest();
        CountDownLatch latch = new CountDownLatch(50);

        ExecutorService service = Executors.newFixedThreadPool(50);
        for (int i = 0; i < 50; i++) {
            service.submit(() -> {
                unsafeTest.increment();
                latch.countDown();
            });
        }

        latch.await();
        service.shutdown();
        System.out.println("anInt:" + unsafeTest.anInt);
    }
}
